package com.yiyuwanglu.basecore.service.impl;

import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import com.yiyuwanglu.basecore.page.Page;
import com.yiyuwanglu.basecore.service.INStatisticsService;
import com.yiyuwanglu.basecore.vo.QueryMongoVo;

@Service("nStatisticsService")
public class NStatisticsServiceImpl implements INStatisticsService{

	@Autowired
	private com.yiyuwanglu.basecore.dao.MongoDBBaseDao mongoDBBaseDao;

	@Override
	public <T> List<T> getInfo(Class<T> entityClass, QueryMongoVo queryVo,String collectionName) {
		return mongoDBBaseDao.findByQuery(entityClass, getQuery(queryVo), collectionName);
	}
	
	@Override
	public <T> List<T> getStatisticsDetail(Class<T> entityClass, QueryMongoVo queryVo,String collectionName, Page pager) {
		Aggregation aggregation =  getAggregateCreateDateGroup(queryVo);
		// 查询出总条数
		int count = mongoDBBaseDao.aggregate(aggregation, collectionName, entityClass).getMappedResults().size();
		aggregation =  getAggregateCreateDate(queryVo, count, pager);
		// 查询结果
		return mongoDBBaseDao.aggregate(aggregation, collectionName, entityClass).getMappedResults();
	}
	// 分组查询
	private Aggregation getAggregateCreateDateGroup(QueryMongoVo queryVo){
		
		  AggregationOperation match = Aggregation.match(getCriteria(queryVo));
		  //查询聚合结果
		 AggregationOperation group = Aggregation.group("loginName").first("ip").as("ip").first("userId").as("userId")
				 .max("createDate").as("createDate").max("loginName").as("loginName").count().as("count");
		  Direction direction = Direction.DESC;
		  AggregationOperation sort = Aggregation.sort(new Sort(direction,"createDate"));
		  Aggregation aggregation =  Aggregation.newAggregation(match,group,sort);
		
		  return aggregation;
		
	}
	// 加分页查询条件
	private Aggregation getAggregateCreateDate(QueryMongoVo queryVo,
			int count, Page pager) {
		
		AggregationOperation match = Aggregation.match(getCriteria(queryVo));
		//查询聚合结果
		AggregationOperation group = Aggregation.group("loginName").first("ip").as("ip").first("userId").as("userId")
		.max("createDate").as("createDate").max("loginName").as("loginName").count().as("count");
		Direction direction = Direction.DESC;
		AggregationOperation sort = Aggregation.sort(new Sort(direction,"createDate"));
		// 分页
		pager.setTotalCount(count);
		int pageNumber = pager.getPageNo();
		int pageSize = pager.getPageSize();
		AggregationOperation limit = Aggregation.limit(pageSize);
		AggregationOperation skip = Aggregation.skip((pageNumber - 1) * pageSize);
		Aggregation aggregation =  Aggregation.newAggregation(match,group,sort, skip, limit);
		return aggregation;
	}
	
	/**
	 * 根据 QueryMongoVo 赋值 Mongo Query
	 * 
	 * @param queryVo
	 * @return Query
	 */
	private Query getQuery(QueryMongoVo queryVo) {

		Query query = new Query();
		Criteria criteria = new Criteria();
		if (StringUtils.isNotBlank(queryVo.getIp())) {
			criteria.and("ip").is(queryVo.getIp());
		}
		
		if (StringUtils.isNotBlank(queryVo.getLoginName())) {
			criteria.and("loginName").in(queryVo.getLoginName());
		}
		
		if (StringUtils.isNotBlank(queryVo.getUserId())) {
			criteria.and("userId").is(queryVo.getUserId());
		}
		
		if(StringUtils.isNotBlank(queryVo.getStartDate())){
			criteria.and("createDate").gte(queryVo.getStartDate());
		}
		if(StringUtils.isNotBlank(queryVo.getEndDate())){
			criteria.and("createDate").lte(queryVo.getEndDate());
		}
		query.addCriteria(criteria);
		
		return query;

	}
	
	/**
	 * 根据 QueryMongoVo 赋值 Mongo getCriteria
	 * 
	 * @param queryVo
	 * @return Criteria
	 */
	private Criteria getCriteria(QueryMongoVo queryVo) {

		Criteria criteria = new Criteria();
		
		if (StringUtils.isNotBlank(queryVo.getIp())) {
			criteria.and("ip").is(queryVo.getIp());
		}
		
		if (StringUtils.isNotBlank(queryVo.getLoginName())) {
			criteria.and("loginName").in(queryVo.getLoginName().split(","));
		}
		//1未登录
		if("2".equals(queryVo.getFlagLogin())){
			criteria.and("loginName").is("");
		}//2登录
		else if("1".equals(queryVo.getFlagLogin())){
			criteria.and("loginName").ne("");
		}
		
		if(StringUtils.isNotBlank(queryVo.getStartDate()) && StringUtils.isBlank(queryVo.getEndDate())){
			criteria.and("createDate").gte(queryVo.getStartDate());
		}
		if(StringUtils.isBlank(queryVo.getStartDate()) && StringUtils.isNotBlank(queryVo.getEndDate())){
			criteria.and("createDate").lte(queryVo.getEndDate());
		}
		if(StringUtils.isNotBlank(queryVo.getStartDate()) && StringUtils.isNotBlank(queryVo.getEndDate())){
//			criteria.where("createDate").gte(queryVo.getStartDate()).and("createDate").lte(queryVo.getEndDate());
//			criteria.and("createDate").gte(queryVo.getStartDate()).and("createDate").lte(queryVo.getEndDate());
			criteria.andOperator(Criteria.where("createDate").gte(queryVo.getStartDate()), Criteria.where("createDate").lte(queryVo.getEndDate()));
		}
		
		return criteria;

	}

	@Override
	public <T> List<T> getStatisticsDetail(Class<T> entityClass,
			QueryMongoVo queryVo, String collectionName) {
		// 无聚合分组查询
		Aggregation aggregation =  getAggregateCreateDate(queryVo);
		
		// 查询结果
		return mongoDBBaseDao.aggregate(aggregation, collectionName, entityClass).getMappedResults();
	}
	private Aggregation getAggregateCreateDate(QueryMongoVo queryVo){
		
		  AggregationOperation match = Aggregation.match(getCriteria(queryVo));
		  Direction direction = Direction.DESC;
		  AggregationOperation sort = Aggregation.sort(new Sort(direction,"createDate"));
		  Aggregation aggregation =  Aggregation.newAggregation(match,sort);
		
		  return aggregation;
		
	}
}
